#ifndef __CALL_HANDLER_H__
#define __CALL_HANDLER_H__

class Call {
public:
    Call();
    ~Call();
    void reply(string msg) { }
    void disconnect() { }

private:
    int rank;
}
    

class Employee {
public:
    Employee();
    ~Employee();

    bool isBusy() { return is_busy_; }
    void setStatus(bool busy) {
        is_busy_ = busy;
    }

    virtual bool ableToHandle(Call call) = 0;

    void receiveCall(Call call);
    void handleCall(Call call);

private:
    char name[256];
    bool is_busy_;
    int rank;
};

class Fresher : public Employee {
public:
    Fresher();
    ~Fresher();

    virtual bool ableToHandle(Call call);
};

class TLead : public Employee {
public:
    TLead();
    ~TLead();
    virtual bool ableToHandle(Call call);
};

class ProductManager : public Employee {
public:
    ProductManager();
    ~ProductManager();
    virtual bool ableToHandle(Call call);
};

class CallHandler {
public:
    CallHandler();
    ~CallHandler();

    Employee *getCallHandler(Call call);
    void dispatchCall(Call call);
    Call *getNextCall();

private:
    Employee *getFreeFresher();

private:
    Fresher *fresher_;
    TLead tech_leader_;
    ProductManager prod_manager_;

    Call *calls_;
}

void CallHandler::dispatchCall(Call call) {
    Employee *handler = getCallHandler(Call);
    if (handler == NULL) {
        addToList(call);
    }
    else {
        bool ableToHandle = handler->ableToHandle(call);
        if (ableToHandle) {
            handler->handleCall(call);
        }
        else {
            call.increaseRank();
            addToList(call);
        }
    }

    return;
}

Empolyee * CallHandler::getCallHandler(Call call) {
    Fresher *fresher = getFreeFresher();
    Employee *handler = NULL;
    if (fresher == NULL) {
        handler = &tech_leader_;
    }
    else {
        if (fresher.abToHandle(call)) {
            return fresher;
        }
        else {
            handler = &tech_leader;
        }
    }

    if (handler->isBusy() == false && 
        handler->ableToHandle(call) == true) {
        return handler;
    }
    else {
        handler = &prod_manager_;
    }

    if (handler->isBusy() == false &&
        handler->ableToHandle(call) == true) {
        return handler;
    }
    else {
        return NULL;
    }
}

#endif

